//
//  WatchFileSyncService.swift
//  WatchFileSyncService.swift
//
//  Created by tangjilin on 2025/7/16.
//

import Foundation
import WatchConnectivity
import Combine
import UserNotifications
import SwiftUI

// 错误类型
enum SyncError: Error {
    case watchConnectivityNotSupported
    case sessionNotActivated
    case watchNotPairedOrAppNotInstalled
    case watchNotReachable
    case sessionActivationFailed(Error)
    case messageSendFailed(Error)
    case fileSaveFailed(Error)
    case fileDeletionFailed(Error)
    
    var localizedDescription: String {
        switch self {
        case .watchConnectivityNotSupported:
            return "Watch Connectivity不支持此设备"
        case .sessionNotActivated:
            return "Watch Connectivity会话未激活"
        case .watchNotPairedOrAppNotInstalled:
            return "Apple Watch未配对或Watch应用未安装"
        case .watchNotReachable:
            return "Apple Watch不可达"
        case .sessionActivationFailed(let error):
            return "会话激活失败: \(error.localizedDescription)"
        case .messageSendFailed(let error):
            return "消息发送失败: \(error.localizedDescription)"
        case .fileSaveFailed(let error):
            return "保存文件失败: \(error.localizedDescription)"
        case .fileDeletionFailed(let error):
            return "删除文件失败: \(error.localizedDescription)"
        }
    }
}

// 同步状态枚举
enum SyncStatus {
    case idle, syncing, completed, failed
}

// 文件类型枚举
enum FileType {
    case image, video, audio, document, text, caf, unknown
    
    // 获取文件类型图标
    var icon: String {
        switch self {
        case .image: return "photo"
        case .video: return "film"
        case .audio: return "music.note"
        case .document: return "doc"
        case .text: return "doc.text"
        case .caf: return "waveform.path.ecg"
        case .unknown: return "questionmark.square"
        }
    }
    
    // 获取文件类型颜色
    @available(iOS 13.0, *)
    var color: Color {
        switch self {
        case .image: return .blue
        case .video: return .red
        case .audio: return .green
        case .document: return .orange
        case .text: return .purple
        case .caf: return .pink
        case .unknown: return .gray
        }
    }
}

// 文件项模型
struct FileItem: Identifiable {
    let id = UUID()
    let url: URL
    let name: String
    let size: Int64
    let modificationDate: Date
    let type: FileType
    
    // 格式化文件大小
    var formattedSize: String {
        let formatter = ByteCountFormatter()
        formatter.allowedUnits = [.useMB, .useGB]
        formatter.countStyle = .file
        return formatter.string(fromByteCount: size)
    }
    
    // 格式化日期
    var formattedDate: String {
        let formatter = DateFormatter()
        formatter.dateStyle = .medium
        formatter.timeStyle = .short
        return formatter.string(from: modificationDate)
    }
}

@available(iOS 13.0, *)
@MainActor // 确保所有属性的访问和修改都在主线程上进行
class WatchFileSyncService: NSObject, ObservableObject, WCSessionDelegate {
    nonisolated func sessionDidBecomeInactive(_ session: WCSession) {
    }
    
    nonisolated func sessionDidDeactivate(_ session: WCSession) {
        
    }
    
    @MainActor static let shared = WatchFileSyncService()
    
    @Published var receivedFiles: [FileItem] = []
    @Published var syncStatus: SyncStatus = .idle
    @Published var syncError: Error?
    
    private let session = WCSession.default
    private let fileManager = FileManager.default
    private var pendingSyncCompletion: ((Result<Void, Error>) -> Void)?
    
    override init() {
        super.init()
        setupSession()
    }
    
    // 设置Watch Connectivity会话
    private func setupSession() {
        guard WCSession.isSupported() else {
            syncError = SyncError.watchConnectivityNotSupported
            return
        }
        
        if session.activationState != .activated {
            session.delegate = self
            session.activate()
            print("Watch Connectivity会话已激活")
        }
    }
    
    // 手机主动请求同步文件
    func requestSyncFromWatch(completion: ((Result<Void, Error>) -> Void)? = nil) {
        guard session.activationState == .activated else {
            let error = SyncError.sessionNotActivated
            syncError = error
            completion?(.failure(error))
            return
        }
        
        guard session.isPaired && session.isWatchAppInstalled else {
            let error = SyncError.watchNotPairedOrAppNotInstalled
            syncError = error
            completion?(.failure(error))
            return
        }
        
        guard session.isReachable else {
            let error = SyncError.watchNotReachable
            syncError = error
            completion?(.failure(error))
            return
        }
        
        pendingSyncCompletion = completion
        syncStatus = .syncing
        
        // 发送同步请求到Apple Watch
        let message = ["request": "syncFiles", "timestamp": Date().timeIntervalSince1970] as [String : Any]
        session.sendMessage(message, replyHandler: { [weak self] response in
            // 复制需要使用的变量到本地常量
            let localCompletion = self?.pendingSyncCompletion
            
            Task { @MainActor in
                self?.syncStatus = .completed
                localCompletion?(.success(()))
                self?.pendingSyncCompletion = nil
                print("同步请求已发送到Apple Watch")
            }
        }) { [weak self] error in
            Task { @MainActor in
                self?.syncStatus = .failed
                self?.syncError = SyncError.messageSendFailed(error)
                self?.pendingSyncCompletion?(.failure(error))
                self?.pendingSyncCompletion = nil
                print("发送同步请求失败: \(error)")
            }
        }
    }
    
    // 获取文件信息
    func getFileInfo(for url: URL) -> FileItem? {
        guard let attributes = try? fileManager.attributesOfItem(atPath: url.path) else {
            return nil
        }
        
        return FileItem(
            url: url,
            name: url.lastPathComponent,
            size: attributes[.size] as? Int64 ?? 0,
            modificationDate: attributes[.modificationDate] as? Date ?? Date(),
            type: fileType(for: url.pathExtension)
        )
    }
    
    // 删除文件
    func deleteFile(at url: URL) -> Bool {
        do {
            try fileManager.removeItem(at: url)
            receivedFiles.removeAll { $0.url == url }
            return true
        } catch {
            syncError = SyncError.fileDeletionFailed(error)
            return false
        }
    }
    
    // 会话激活完成回调
    nonisolated func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {
        print("会话激活完成: \(activationState)")
        if let error = error {
            // 切换到主线程修改 @MainActor 属性
            Task { @MainActor in
                self.syncError = SyncError.sessionActivationFailed(error)
            }
        }
    }
    // 会话可达性变化回调
    nonisolated func sessionReachabilityDidChange(_ session: WCSession) {
        print("Watch可达性变化: \(session.isReachable)")
    }
    
    // 接收文件回调
    nonisolated func session(_ session: WCSession, didReceive file: WCSessionFile) {
        // 1. 立即复制需要的元数据到本地常量
        let fileName = file.metadata?["fileName"] as? String ?? UUID().uuidString
        let fileURL = file.fileURL // 保存文件URL
        
        Task { @MainActor in
            do {
                let documentsURL = try fileManager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
                let destinationURL = documentsURL.appendingPathComponent(fileName)
                
                // 如果文件已存在，先删除
                if fileManager.fileExists(atPath: destinationURL.path) {
                    try fileManager.removeItem(at: destinationURL)
                }
                
                // 2. 使用保存的 fileURL 而不是原始的 file 对象
                try fileManager.moveItem(at: fileURL, to: destinationURL)
                print("文件已保存到: \(destinationURL)")
                
                // 添加到文件列表
                if let fileItem = getFileInfo(for: destinationURL) {
                    receivedFiles.append(fileItem)
                }
                
                // 通知用户
                showNotification(for: fileName)
            } catch {
                syncError = SyncError.fileSaveFailed(error)
                print("保存文件失败: \(error)")
            }
        }
    }
    
    // 接收消息回调（用于从Watch接收数据）
    nonisolated func session(_ session: WCSession, didReceiveMessage message: [String : Any]) {
        // 提取必要的基本类型参数
        let requestType = message["request"] as? String
        let fileName = message["fileName"] as? String
        let fileSize = message["fileSize"] as? Int64
        
        Task { @MainActor in
            // 在 @MainActor 上下文中创建全新的消息字典
            var safeMessage: [String: Any] = [:]
            
            // 安全地添加基本类型参数
            if let requestType = requestType {
                safeMessage["request"] = requestType
            }
            
            if let fileName = fileName {
                safeMessage["fileName"] = fileName
            }
            
            if let fileSize = fileSize {
                safeMessage["fileSize"] = fileSize
            }
        
            print("收到消息: \(safeMessage)")
            
            // 使用本地创建的 safeMessage 处理请求
            if let request = requestType {
                switch request {
                case "syncFiles":
                    // 处理文件同步请求
                    break
                case "deleteFile":
                    // 处理删除文件请求
                    break
                default:
                    print("未知请求: \(request)")
                }
            }
        }
    }
    
    // 显示通知
    private func showNotification(for fileName: String) {
        let center = UNUserNotificationCenter.current()
        
        // 检查权限
        center.getNotificationSettings { settings in
            guard settings.authorizationStatus == .authorized else { return }
            
            let content = UNMutableNotificationContent()
            content.title = "新文件已同步"
            content.body = "已接收文件: \(fileName)"
            content.sound = .default
            
            let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 1, repeats: false)
            let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
            
            center.add(request)
        }
    }
    
    // 确定文件类型
    private func fileType(for `extension`: String) -> FileType {
        switch `extension`.lowercased() {
        case "jpg", "jpeg", "png", "gif", "bmp":
            return .image
        case "mp4", "mov", "avi", "mkv":
            return .video
        case "mp3", "wav", "aac", "m4a":
            return .audio
        case "pdf", "doc", "docx", "xls", "xlsx", "ppt", "pptx":
            return .document
        case "txt", "rtf", "md":
            return .text
        case "caf":
            return .caf
        default:
            return .unknown
        }
    }
}
